package org.example.hw.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.PostLoad;
import javax.persistence.Table;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.envers.Audited;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.URL;

@Entity
@Table(name = "HW_LINKS")
@Audited
public class Link extends AbstractEntity {

	public enum Visibility {
		PUBLIC, // Link is visible by other users
		PRIVATE, // Link is not visible by other users
		CUSTOM // Link is visible only to users whose email address is provided by user who owns the link
	}

	@NotBlank
	@URL
	private String originalUrl;

	@NotBlank
	private String customUrl;

	private Visibility visibility = Visibility.PRIVATE;

	// TODO: autoinkrement neka anotacija - svaki put kada se povuce iz baze
	// TODO: atribut u hash, equals, tostring i u DTO
	private Long count = 0L;

	@OneToMany(mappedBy = "link", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
	private Set<EmailAllowed> emailsAllowedList = new HashSet<EmailAllowed>();

	public Link() {

	}

	@PostLoad
	public void incrementCount() {
		this.count++;
	}

	public String getOriginalUrl() {
		return originalUrl;
	}

	public void setOriginalUrl(String originalUrl) {
		this.originalUrl = originalUrl;
	}

	public String getCustomUrl() {
		return customUrl;
	}

	public void setCustomUrl(String customUrl) {
		this.customUrl = customUrl;
	}

	public Visibility getVisibility() {
		return visibility;
	}

	public void setVisibility(Visibility visibility) {
		this.visibility = visibility;
	}

	public Long getCount() {
		return count;
	}

	public void setCount(Long count) {
		this.count = count;
	}

	public Set<EmailAllowed> getEmailsAllowedList() {
		return emailsAllowedList;
	}

	public void setEmailsAllowedList(Set<EmailAllowed> emailsAllowedList) {
		this.emailsAllowedList = emailsAllowedList;
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().
				appendSuper(super.hashCode()).
				append(originalUrl).
				append(customUrl).
				append(visibility).
				append(count).
				hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (obj == this) {
			return true;
		}
		if (obj.getClass() != getClass()) {
			return false;
		}

		final Link otherLink = (Link) obj;

		return new EqualsBuilder().
				appendSuper(super.equals(obj)).
				append(originalUrl, otherLink.getOriginalUrl()).
				append(customUrl, otherLink.getCustomUrl()).
				append(visibility, otherLink.getVisibility()).
				append(count, otherLink.getCount()).
				isEquals();
	}

	@Override
	public String toString() {
		return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).
				append("originalUrl", originalUrl).
				append("customUrl", customUrl).
				append("visibility", visibility).
				append("count", count).
				appendSuper(super.toString()).
				toString();
	}

}
